#include "stdafx.h"
#include "ZNetworkReceiveBuffer.h"
#include "ZStream.h"
#include "ZUtility.h"

namespace	Z	{

//------------------------------------------------------------------------------------------------------------------------
NetworkReceiveBuffer::NetworkReceiveBuffer()
{
}

NetworkReceiveBuffer::~NetworkReceiveBuffer()
{
}

size_t NetworkReceiveBuffer::getWsaBufCount()	const
{
	size_t unwritableBufCount	= 0;
	for(Streams::const_iterator i = mStreams.begin(); i != mStreams.end(); ++i)	{
		if(0 < (*i)->getWritableSize())
			return mStreams.size() - unwritableBufCount;
		++unwritableBufCount;
	}
	return 0;
}

void NetworkReceiveBuffer::getWsaBufs(WSABUF* kWsaBufs, size_t kWsaBufCount)	const
{
	assert(kWsaBufCount <= getWsaBufCount());

	Streams::const_iterator first	= mStreams.begin();
	std::advance(first, mStreams.size() - getWsaBufCount());
	size_t w	= 0;
	for(Streams::const_iterator i = first; w < kWsaBufCount; ++i)	{
		assert(w < kWsaBufCount);
		kWsaBufs[w].buf	= (char*)(*i)->getWritableBuffer();
		kWsaBufs[w++].len	= (*i)->getWritableSize();
	}
}

void NetworkReceiveBuffer::reserve(size_t kSize)
{
	const size_t streamSize	= std::max<size_t>(kSize, Stream::autoSize);
	if(getReceivableSize() < streamSize)	{
		mStreams.push_back(new Stream(streamSize));
	}

	//if(kSize <= getReceivableSize())
	//	return;

	//const size_t count	= kSize / Stream::autoSize + 1;
	//for(size_t i = 0; i < count; ++i)	{
	//	mStreams.push_back(new Stream(Stream::autoSize));
	//}
}

void NetworkReceiveBuffer::onComplete(size_t bytesTransferred)
{
	size_t transferred	= bytesTransferred;
	for(Streams::iterator i = mStreams.begin(); i != mStreams.end(); ++i)	{
		Stream* pStream	= *i;
		const size_t writableSize	= std::min<size_t>(pStream->getWritableSize(), transferred);
		pStream->onWritten(writableSize);
		transferred	-= writableSize;
		if(transferred == 0)
			break;
	}

	assert(transferred == 0);
}

void NetworkReceiveBuffer::peek(void* data, size_t kSize)	const
{
	assert(kSize <= getReadableSize());

	size_t readSize	= 0;
	for(Streams::const_iterator i = mStreams.begin(); i != mStreams.end(); ++i)	{
		Stream* pStream	= *i;
		const size_t readableSize	= std::min<size_t>(pStream->getReadableSize(), kSize - readSize);
		pStream->peek((byte_t*)data + readSize, readableSize);
		readSize	+= readableSize;
		if(readSize == kSize)
			break;
	}
}

void NetworkReceiveBuffer::pop(size_t kSize)
{
	assert(kSize <= getReadableSize());

	size_t readSize	= 0;
	for(Streams::iterator i = mStreams.begin(); i != mStreams.end();)	{
		Stream* pStream	= *i;
		const size_t readableSize	= std::min<size_t>(pStream->getReadableSize(), kSize - readSize);
		pStream->pop(readableSize);
		if(pStream->getReadableSize() == 0)	{
			i	= mStreams.erase(i);
			deletePtr(pStream);
		}
		else	{
			++i;
		}
		readSize	+= readableSize;
		if(readSize == kSize)
			break;
	}
}

}